/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
/*
 * TrainingBook
 * Copyright (C) Arnaud Duval 2010 <arnaud.duval@gmail.com>
 * 
 * Projects is free software: you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the
 * Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * Projects is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License along
 * with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "activity-analysis-dialog.hpp"
#include <iostream>

///@brief Constructor
///@param Dactivity The activity to be analysed
ActivityAnalysisDialog::ActivityAnalysisDialog(Activity Dactivity) : Gtk::Dialog()
{
    activity = Dactivity;

    //Set the size of the window
    set_default_size(800,400);
    //Set the border width of the window
    set_border_width(0);

    theMap.set_size_request(400,400);
    ///@warning A bouding box should be set
    /*theMap.SetBoundingBox(activity.GetTrack().MinLat(),
                          activity.GetTrack().MaxLat(),
                          activity.GetTrack().MinLon(),
                          activity.GetTrack().MaxLon());*/
    theMap.SetZoomLevel(10);
    theMap.SetTilesRepository("http://tile.openstreetmap.org/");
    theCurves.set_size_request(400, 300);

    ///@brief Setting the work track
    //work_track = activity.GetTrack();
    UpdateMap();
    UpdateCurves();
    UpdateTrackInformations();

    ///@brief Setting the filter tool bar
    filterApplyButton.set_label("Appliquer le filtre");
    filterApplyButton.signal_clicked().connect(sigc::mem_fun(*this,
                    &ActivityAnalysisDialog::on_button_apply_filter_clicked));
    filterResetButton.set_label("RAZ filtre");
    filterResetButton.signal_clicked().connect(sigc::mem_fun(*this,
                    &ActivityAnalysisDialog::on_button_reset_filter_clicked));

    //Penser à envoyer un signal

    filterTypeCBT.append_text("Filtre par distance");
    filterTypeCBT.append_text("Filtre par variation d'altitude");
    filterTypeCBT.set_active(0);

    smoothButton.set_label("Lissage");
    smoothButton.signal_clicked().connect(sigc::mem_fun(*this,
                   &ActivityAnalysisDialog::on_button_smooth_elevation_clicked));

    map_curveHBox.pack_start(theMap, Gtk::PACK_EXPAND_WIDGET);
    map_curveHBox.pack_end(theCurves, Gtk::PACK_EXPAND_WIDGET);

    filterHBox.pack_start(filterTypeCBT, Gtk::PACK_SHRINK);
    filterHBox.pack_start(filterEntry, Gtk::PACK_SHRINK);
    filterHBox.pack_start(filterApplyButton, Gtk::PACK_SHRINK);
    filterHBox.pack_start(filterResetButton, Gtk::PACK_SHRINK);

    smoothHBox.pack_start(smoothEntry, Gtk::PACK_SHRINK);
    smoothHBox.pack_start(smoothButton, Gtk::PACK_SHRINK);

    infoHBox.pack_start(distanceLabel, Gtk::PACK_EXPAND_WIDGET);
    infoHBox.pack_start(totalAscentLabel, Gtk::PACK_EXPAND_WIDGET);
    infoHBox.pack_start(totalDescentLabel, Gtk::PACK_EXPAND_WIDGET);
    infoHBox.pack_start(averageSpeedLabel, Gtk::PACK_EXPAND_WIDGET);
    infoHBox.pack_start(maxSpeedLabel, Gtk::PACK_EXPAND_WIDGET);

    get_vbox()->pack_start(map_curveHBox, Gtk::PACK_EXPAND_WIDGET);
    get_vbox()->pack_start(filterHBox, Gtk::PACK_SHRINK);
    get_vbox()->pack_start(smoothHBox, Gtk::PACK_SHRINK);
    get_vbox()->pack_start(infoHBox, Gtk::PACK_EXPAND_WIDGET);

    show_all();
}

///@brief Destructor
ActivityAnalysisDialog::~ActivityAnalysisDialog()
{

}

///@brief Set the analysed activity
///@param Dactivity Activity to be set
void ActivityAnalysisDialog::SetActivity(Activity Dactivity)
{
    activity = Dactivity;
}

///@brief Update the map with the work track
void ActivityAnalysisDialog::UpdateMap()
{
    theMap.ClearTracks();
    if(!work_track.Empty())
        theMap.AddTrack(work_track);
}

///@brief Update the curves with the work track
void ActivityAnalysisDialog::UpdateCurves()
{
    theCurves.ClearXList();
    theCurves.ClearYList(0);
    theCurves.ClearYList(1);

    std::list<double> dist_list = work_track.GetDistanceList();
    ///@bug doesn't work with direct call to GetDistanceList()
    //theCurves.SetXList(work_track.GetDistanceList());
    theCurves.SetXList(dist_list);
    theCurves.SetXRange(0., work_track.Length());
    
    theCurves.SetYList(work_track.GetElevationList(), 0);
    theCurves.SetYRange(work_track.MinElevation(), work_track.MaxElevation(), 0);
    
    theCurves.SetYList(work_track.GetSpeedList(), 1);
    theCurves.SetYRange(0., work_track.MaxSpeed(), 1);

    theCurves.queue_draw();
}

///@brief Update the displayed track information with the work track
void ActivityAnalysisDialog::UpdateTrackInformations()
{
    std::ostringstream distanceStringValue, totalAscentStringValue, totalDescentStringValue,
                       averageSpeedStringValue, maxSpeedStringValue;
    double distance = work_track.Length();
    distanceStringValue << distance;
    totalAscentStringValue << work_track.TotalAscent();
    totalDescentStringValue << work_track.TotalDescent();

    ///TO BE CONTINUED
    
    distanceLabel.set_text("Distance : " + distanceStringValue.str() + " km");
    totalAscentLabel.set_text("D+ : " + totalAscentStringValue.str() + " m");
    totalDescentLabel.set_text("D- : " + totalDescentStringValue.str() + " m");
    averageSpeedLabel.set_text("vit. moy : " + averageSpeedStringValue.str() + " km/h");
    maxSpeedLabel.set_text("vit. max : " + maxSpeedStringValue.str() + " km/h");
}

///@brief Action when clicking on the "apply filter" button
void ActivityAnalysisDialog::on_button_apply_filter_clicked()
{
    if(filterTypeCBT.get_active_text() == "Filtre par distance")
    {
        work_track.FilterByDistance(filterEntry.GetValue());
        UpdateMap();
        UpdateCurves();
        UpdateTrackInformations();
    }
    else if(filterTypeCBT.get_active_text() == "Filtre par variation d'altitude")
    {
        work_track.FilterByElevationVariation(filterEntry.GetValue());
        UpdateMap();
        UpdateCurves();
        UpdateTrackInformations();
    }
    //work_track.WriteForDebug();
}

///@brief Action when clicking on the "reset filter" button
void ActivityAnalysisDialog::on_button_reset_filter_clicked()
{
    //work_track = activity.GetTrack();
    //work_track.WriteForDebug();
    UpdateMap();
    UpdateCurves();
    UpdateTrackInformations();
}

///@brief Action when clicking on the "smooth elevation" button
void ActivityAnalysisDialog::on_button_smooth_elevation_clicked()
{
    work_track.SmoothElevation(smoothEntry.GetValue());
    ///Temporaire
    work_track.RecomputeSpeed();
    UpdateMap();
    UpdateCurves();
    UpdateTrackInformations();
}
